#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
#include "driver/gpio.h"
#include "esp_adc/adc_oneshot.h"
#include "led_strip.h"

static const char *TAG = "PS_STICK_LED";

// 硬件配置
#define LED_STRIP_GPIO     40    // WS2812B数据引脚
#define NUM_LEDS           30     // LED数量，根据你的灯带调整
#define PS_VRX_CHANNEL     ADC_CHANNEL_8  // GPIO9 - PS摇杆X轴
#define PS_VRY_CHANNEL     ADC_CHANNEL_9  // GPIO10 - PS摇杆Y轴  
#define PS_SW_GPIO         11     // PS摇杆按键

// 控制配置
#define ADC_READ_THRESHOLD 300    // 摇杆读取阈值
#define MOVE_DELAY         100    // 移动延迟（ms）

static led_strip_handle_t strip = NULL;
static adc_oneshot_unit_handle_t adc1_handle = NULL;
static int current_position = 0;      // 当前LED位置
static int current_color_mode = 0;    // 当前颜色模式
static int current_brightness = 255;  // 当前亮度 (0-255)

// 颜色定义
typedef struct {
    uint8_t r, g, b;
} rgb_t;

// 预定义颜色
static const rgb_t colors[] = {
    {255, 0, 0},    // 红色
    {0, 255, 0},    // 绿色
    {0, 0, 255},    // 蓝色
    {255, 255, 0},  // 黄色
    {255, 0, 255},  // 紫色
    {0, 255, 255},  // 青色
    {255, 255, 255},// 白色
    {255, 128, 0},  // 橙色
};

#define NUM_COLORS (sizeof(colors) / sizeof(colors[0]))

// 初始化LED灯带
static esp_err_t init_led_strip(void)
{
    led_strip_config_t strip_config = {
        .strip_gpio_num = LED_STRIP_GPIO,
        .max_leds = NUM_LEDS,
    };

    led_strip_rmt_config_t rmt_config = {
        .resolution_hz = 10 * 1000 * 1000, // 10MHz
    };

    ESP_ERROR_CHECK(led_strip_new_rmt_device(&strip_config, &rmt_config, &strip));
    ESP_LOGI(TAG, "LED strip initialized with %d LEDs", NUM_LEDS);
    return ESP_OK;
}

// 初始化PS摇杆
static esp_err_t init_joystick(void)
{
    // 配置ADC
    adc_oneshot_unit_init_cfg_t init_config1 = {
        .unit_id = ADC_UNIT_1,
        .ulp_mode = ADC_ULP_MODE_DISABLE,
    };
    ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle));

    adc_oneshot_chan_cfg_t config = {
        .bitwidth = ADC_BITWIDTH_DEFAULT,
        .atten = ADC_ATTEN_DB_12,
    };
    ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, PS_VRX_CHANNEL, &config));
    ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, PS_VRY_CHANNEL, &config));
    
    // 配置按键
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << PS_SW_GPIO),
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_DISABLE,
    };
    gpio_config(&io_conf);
    
    ESP_LOGI(TAG, "Joystick initialized");
    return ESP_OK;
}

// 读取摇杆状态
static void read_joystick(int *x, int *y, bool *button)
{
    adc_oneshot_read(adc1_handle, PS_VRX_CHANNEL, x);
    adc_oneshot_read(adc1_handle, PS_VRY_CHANNEL, y);
    *button = !gpio_get_level(PS_SW_GPIO);  // 按下时为低电平
}

// 清除所有LED
static void clear_all_leds(void)
{
    ESP_ERROR_CHECK(led_strip_clear(strip));
}

// 设置单个LED颜色（带亮度调节）
static void set_led_color(int index, rgb_t color)
{
    if (index >= 0 && index < NUM_LEDS) {
        // 根据亮度调节颜色
        uint8_t r = (color.r * current_brightness) / 255;
        uint8_t g = (color.g * current_brightness) / 255;
        uint8_t b = (color.b * current_brightness) / 255;
        ESP_ERROR_CHECK(led_strip_set_pixel(strip, index, r, g, b));
    }
}

// 刷新LED显示
static void refresh_leds(void)
{
    ESP_ERROR_CHECK(led_strip_refresh(strip));
}

// 更新LED位置和颜色
static void update_led_position(void)
{
    int x, y;
    bool button;
    static bool last_button = false;
    
    read_joystick(&x, &y, &button);
    
    // 处理按键切换颜色（检测按键按下事件）
    if (button && !last_button) {
        current_color_mode = (current_color_mode + 1) % NUM_COLORS;
        ESP_LOGI(TAG, "Color changed to mode %d", current_color_mode);
    }
    last_button = button;
    
    // 处理X轴移动（左右）
    if (x > (2048 + ADC_READ_THRESHOLD)) {
        // 向左移动
        if (current_position > 0) {
            current_position--;
            ESP_LOGI(TAG, "Position: %d", current_position);
        }
    } else if (x < (2048 - ADC_READ_THRESHOLD)) {
        // 向右移动
        if (current_position < NUM_LEDS - 1) {
            current_position++;
            ESP_LOGI(TAG, "Position: %d", current_position);
        }
    }
    
    // 处理Y轴亮度调节（上下）
    if (y > (2048 + ADC_READ_THRESHOLD)) {
        // 向上推摇杆 - 增加亮度
        if (current_brightness < 255) {
            current_brightness += 5;
            if (current_brightness > 255) current_brightness = 255;
            ESP_LOGI(TAG, "Brightness: %d", current_brightness);
        }
    } else if (y < (2048 - ADC_READ_THRESHOLD)) {
        // 向下推摇杆 - 减少亮度
        if (current_brightness > 0) {
            current_brightness -= 5;
            if (current_brightness < 0) current_brightness = 0;
            ESP_LOGI(TAG, "Brightness: %d", current_brightness);
        }
    }
    
    // 更新LED显示
    clear_all_leds();
    set_led_color(current_position, colors[current_color_mode]);
    refresh_leds();
}

// 启动动画
static void show_startup_animation(void)
{
    ESP_LOGI(TAG, "Starting LED control...");
    
    // 从左到右扫描效果
    for (int i = 0; i < NUM_LEDS; i++) {
        clear_all_leds();
        set_led_color(i, colors[0]); // 红色扫描
        refresh_leds();
        vTaskDelay(pdMS_TO_TICKS(50));
    }
    
    // 从右到左扫描效果
    for (int i = NUM_LEDS - 1; i >= 0; i--) {
        clear_all_leds();
        set_led_color(i, colors[2]); // 蓝色扫描
        refresh_leds();
        vTaskDelay(pdMS_TO_TICKS(50));
    }
    
    clear_all_leds();
    refresh_leds();
    vTaskDelay(pdMS_TO_TICKS(500));
}

void app_main(void)
{
    ESP_LOGI(TAG, "PS摇杆控制LED灯带启动!");
    
    // 初始化硬件
    ESP_ERROR_CHECK(init_led_strip());
    ESP_ERROR_CHECK(init_joystick());
    
    // 显示启动动画
    show_startup_animation();
    
    // 初始化位置
    current_position = NUM_LEDS / 2;  // 从中间开始
    current_color_mode = 0;           // 红色开始
    
    ESP_LOGI(TAG, "控制方式:");
    ESP_LOGI(TAG, "- 摇杆左右: 移动LED位置");
    ESP_LOGI(TAG, "- 摇杆上下: 调节亮度");
    ESP_LOGI(TAG, "- 按下摇杆: 切换颜色");
    ESP_LOGI(TAG, "- 当前位置: %d, 颜色模式: %d, 亮度: %d", current_position, current_color_mode, current_brightness);
    
    // 主循环
    while (1) {
        update_led_position();
        vTaskDelay(pdMS_TO_TICKS(MOVE_DELAY));
    }
}
